local nl = require'luaNumeric'
require 'luaFDTD3D'
local plot = require "Q2DViewerEx"
require "Q3DViewer"

--===========================================================================--
--初始化参数
local FieldsOfView={
	widgets={};
	data={};
	scale = 20;
	set_settings_str = Gallop.set_settings_str;
	get_settings_str = Gallop.get_settings_str;
};
--===========================================================================--

--===========================================================================--
--创建表和创建元表
function FieldsOfView:new (o)
	o = o or {};
	self.__index = self;
	setmetatable(o,self)
	o:init();
	return o;
end
--===========================================================================--

--===========================================================================--
--初始化
function FieldsOfView:init ()

end
--===========================================================================--

--===========================================================================--
--获得视图
function FieldsOfView:get_fields ()
	return self.cfields;
end
--===========================================================================--

--===========================================================================--
--ui交互函数:设置参数按钮
function FieldsOfView:get_border()
	local bbox = self.sph:bbox();
	return -self.scale+bbox:xcenter(),-self.scale+bbox:ycenter(),-self.scale+bbox:zcenter(),
			self.scale+bbox:xcenter(),self.scale+bbox:ycenter(),self.scale+bbox:zcenter();
end
--===========================================================================--

--===========================================================================--
--计算视界
function FieldsOfView:create_view ()
	self:update_scale_from_ui()
	local sph = Geometry.object('sph')
	self.sph = sph;
	local chuan = Geometry.object('chuan')
	local size = sph:bbox():size();
	
	local pt = Geometry.object('Point')
	
	assert( size > 0 , '天线模型尺寸错误')
	assert( self.nmesh < 1000 and self.nmesh > 0, '精度设置太高')
	

	local mesh_soup = Geometry.create_mesh_soup()
	mesh_soup:name('mesh')
	mesh_soup:add_shape(sph:copy())
	mesh_soup:dmax(size/self.nmesh)
	mesh_soup:create_mesh()

	--local px = sph:bbox():xcenter();
	--local py = sph:bbox():ycenter();
	--local pz = sph:bbox():zcenter();
	
	local px = pt:bbox():xcenter();
    local py = pt:bbox():ycenter();
    local pz = pt:bbox():zcenter();

	local rays  = Geometry.create_raytracing()
	rays:mesh( chuan:copy() );

	local pts = mesh_soup:points();
	for kk=1,#pts do 
		--print(pts[kk]);	
		rays:insert_incident_ray(px,py,pz,pts[kk][1]-px,pts[kk][2]-py,pts[kk][3]-pz)
	end

	rays:generate_incidents()
	rays:tracing()

	local traces = rays:traces();

	function Geometry.GLCG_Vector:angle()
		local rho = math.sqrt( self:x()*self:x()+ self:y()*self:y()+self:z()*self:z() )
		local r = math.sqrt( self:x()*self:x()+ self:y()*self:y())
		--local theta = math.asin( r/rho )
		local theta = math.acos( self:z()/rho )
		local c  = nl.new_complex( self:x(), self:y() );
		c = c/c:abs()*theta/pi*2
		return theta,c:arg(),c:real(),c:imag();
	end


	--local cfields = Geometry.create_scalar_complex_fields_array2D()
	local cfields = self:create_fields()
	cfields:set_render_mode(5)
	for kk=1,#traces do 
    	print(traces[kk]:start_ray():direction():z())
		--if  traces[kk]:start_ray():direction():z()>2 then
			theta,phi,x,y = traces[kk]:start_ray():direction():angle() 
			d = nl.new_cvector(1);
			d[1] = 0.;
			if #traces[kk]:rays() >= 1 then
				d[1] = 1;
			end
			--print(x,y,d)
			--print(theta,phi)
			if x==x and y==y then 
				cfields:insert(x,y,d);
			end
		--end
	end

	scale = self.scale;
	cfields:GLColorMap('Jet')
	cfields:show_boundary_edge(true)
	cfields:scale(scale)
	cfields:translate(px,py,pz)
	cfields:build_polyhedron()
	cfields:cut_segment_plane(0.8)

	Geometry.AddShape(rays)
	--Geometry.AddShape(cfields)
	self.cfields = cfields;

	contours = cfields:get_contours();
	writer = Geometry.CGLDXFWriter:new('fov.dxf')
	writer:set_layer("w");
	writer:set_color(255,0,255);
	for k,v in pairs(contours) do 
		print( k,#v )
		for kk,vv in pairs (v) do 
			--print(vv[1][1],vv[1][2],vv[1][3])
			seg = Geometry.create_segment({ scale*vv[1][1],scale*vv[1][2],0,scale*vv[2][1],scale*vv[2][2],0 });
					seg:build_shape()

			writer:write(seg)
		end
	end
	local poly = Geometry.CGLGeneralPolygon2D:new();
	poly:make_circle(scale,0,0)
	writer:write(poly)
	writer:close();
	
	self:update_fields_to_view()
	self:update_border_to_view()
	self:update_view()
	self:init_view2D()
end

return FieldsOfView;
